home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgramD2.iso
/
Borland
/
Borland C++ V5.02
/
SCRIPT.PAK
/
TEMPLATE.SPP
< prev
next >
Wrap
Text File
|
1997-05-06
|
20KB
|
667 lines
//----------------------------------------------------------------------------
// cScript
// (C) Copyright 1995, 1997 by Borland International, All Rights Reserved
//
// TEMPLATE.SPP
// Script component of IDE's Editor Template Editing.
// Provides support services for smart and template editing.
//
// $Revision: 1.4 $
//
//----------------------------------------------------------------------------
// Template.spp
//
// This template class is enabled by simply loading the script file.
// To enable this feature during every use of the IDE place the
// TEMPLATE.SPP file into the startup scipts in the
//
// Options | Environment | Scripting Startup Scripts edit control
//
// Provided is a template description file for files with the extension of
// "c,cpp,h,hpp,spp" named c.tpl. This file is located in the scripts
// subdirectory. In the template editing class the template description
// file is assigned to extensions in the aExtensions array. Each element
// of the array first specifies the extensions that the description file
// will be used for. Next the description file is specified. The
// convention is to name the file "something.tpl" where tpl stands for
// template.
//
// While editing the template activation occurs by entering any number of
// characters within the keyword and then hitting the space bar the number
// of times specified in the nTemplateActivation variable. The default is
// 1. So if you type b and then hit the spacebar the b will be expanded to
// break. If the nTemplateActivate variable is 0 then the activation will
// occur when the tab key is pressed. Therefore as in the previous example
// typing b then hitting the tab will cause the b to be expanded to break.
//
// Within the .tpl file is a keyword followed by the template command.
// The template command is made up of a series of numbers each specifying a
// template command. For example the first line specifies the keyword
// "break" (without the quotes). The template command on the following
// line is:
//
// 7 6 break;3 8 4
//
// The format of the commands are two characters specifying the command.
// Some commands also accept numeric and alpha numeric arguments. Below is
// a list of defines specifying the current list of template commands. When
// a template command has been recognized the text which triggered the
// command is removed then the command is processed.
//
// We can decifer the template command string above by looking at the first
// command "7 " (The space is important). The 7 is defined as TEC_INSERT,
// this command inserts text. The TEC_INSERT command accepts two arguments
// as seen below. The first specifies the number of characters to insert
// then the actual characters follow. So here it is saying that 6 characters
// should be inserted and those six characters are "break;" (not including
// the quotes. Again note that there is a space which follows the 6. This
// allows up to two digit arguments. We can specify up to 99 allowing
// for very large inserts. Next there is a 3 which is TEC_AUTOINDENT this
// command performs the same action as if you press the enter key. In the
// editor. TEC_AUTOINDENT doesn't accept any arguments. The cursors postion
// is now moved to below the break;. In the following the * represents the
// cursor position:
//
// Step 1, "b" is typed:
//
// b*
//
// Step 2, the space bar is hit and the TEC_INSERT command is executed:
//
// break;*
//
// Step 3, the TEC_AUTOINDENT is executed:
//
// break;
// *
//
// Next the 8 represents the TEC_OUTDENT command which moves the cursor
// out (to the left) by one indent level. Now the cursor is positioned
// to allow the next case statement to occur.
//
// Step 4, the TEC_OUTDENT is executed:
//
// break;
// *
//
// Finally the 4 represents the TEC_GETCURSOR. This command records the
// row and column of the cursor. At the end of each command string the
// cursor is placed at the internally recorded row and column. This allows
// for the placement of the cursor within the middle of the command. For
// example the switch command string is:
//
// 7 8 switch (4 7 1 )3 6 7 1 {3 3 7 1 }
//
// Note the 4 following the "(" after the switch text. When the
// command sequence is completed the cursor will be positioned at that point.
// So if you type s and hit the space bar the following expansion will occur
// with the * representing the cursor position:
//
// switch(*)
// {
//
// }
//
// Each command has a two character length allowing for up to 99 commands.
// To add a command simply add a new case to the switch within the
// ExpansionServices method. Examine the existing commands for examples of
// argument parsing.
//
//----------------------------------------------------------------------------
// Template Editing Command Reference.
//----------------------------------------------------------------------------
//
// TEC_NULL
// This command does nothing.
//
// Arguments: None
//
// TEC_ALIGNIN
// This command positions the cursor to the right at the position in which
// on the first previous line a character is present. i.e.
//
// This is line 1.
// *
//
// If the cursor (specified by the asterisk) was below the 'i' in "is"
// when this command executed the cursor would position under the 'l' in
// "line".
//
// Arguments: None.
//
// TEC_AUTOINDENT
// This command is the equivlent of pressing the enter key and having
// the cursor position at the begining of the characters on the previous
// line.
//
// Arguments: None.
//
// TEC_CURSORGET
// This command records the current cursor row and column in the internal
// row and column variables. The cursor will be returned to this
// position at the termination of the command sequence.
//
// Arguments: None.
//
// TEC_CURSORSET
// This command set the cursor to the currently recorded row and column
// variables.
//
// Arguments: None.
//
// TEC_INDENT
// This command moves the cursor to the right by one indent level.
//
// Arguments: None.
//
// TEC_INSERT
// This command inserts the specified text at the current cursor
// location.
//
// Arguments:
// 1) XX Number of characters to insert.
// 2) The characters to insert.
//
// TEC_OUTDENT
// This command moves the cursor to the left by one indent level.
//
// Arguments: None.
//
//----------------------------------------------------------------------------
import IDE;
import editor;
import scriptEngine;
// Template Editing Commands.
#define TEC_NULL 0
#define TEC_ALIGNIN 1
#define TEC_AUTOINDENT 3
#define TEC_CURSORGET 4
#define TEC_CURSORSET 5
#define TEC_INDENT 6
#define TEC_INSERT 7
#define TEC_OUTDENT 8
class TemplateEditing
{
// ---------------------------------------------------------------------------
// Variables
// ---------------------------------------------------------------------------
// Local processing variables.
declare km = IDE.KeyboardManager;
declare bHooked = false;
declare bActivated = false;
// Option Settings.
declare nTemplateActivation = 1;
// Expansion variables.
declare array aExtensions[] = {
{"c,cpp,h,hpp,spp", "c.tpl" }
};
declare nExpansions = 0;
declare aExpansions = new array[];
declare acExpansionFile = "";
declare nExpandableWord = 0;
declare nExpandableBrace = 0;
declare sExpandableWord = NULL;
// Method tracking.
declare mOriginalTab = NULL;
declare mOriginalBrace = NULL;
declare mOriginalEnter = NULL;
declare mOriginalSpacebar = NULL;
// Position tracking/counting.
declare nRow = 0;
declare nColumn = 0;
declare nSpaceCount = 0;
declare nKeysProcessed = 0;
// ---------------------------------------------------------------------------
// Methods
// ---------------------------------------------------------------------------
// Turn on template editing.
AtivateTemplateEditing() { bActivated = true; }
// Turn off template editing.
DeactivateTemplateEditing() { bActivated = false; }
// true == continuous keys.
AreKeysContinuous()
{
if (km.KeysProcessed == nKeysProcessed + 1)
{
nSpaceCount++;
nKeysProcessed = km.KeysProcessed;
return true;
}
else
{
nSpaceCount++;
nKeysProcessed = km.KeysProcessed;
return false;
}
}
// Hook needed events/methods for template editing.
AttachTemplateEditing()
{
//Needtobackup
declare kbd = km.GetKeyboard("Editor");
if (!bHooked)
{
bHooked = true;
if (nTemplateActivation != 0)
{
mOriginalSpacebar = kbd.GetCommand("<Space>");
kbd.Assign("<Space>","te.KeyProcessSpace();");
}
else
{
mOriginalTab = kbd.GetCommand("<Tab>");
kbd.Assign("<Tab>","te.KeyProcessTab();");
}
mOriginalEnter = kbd.GetCommand("<Enter>");
kbd.Assign("<Enter>","te.KeyProcessEnter();");
mOriginalBrace = kbd.GetCommand("<{>");
kbd.Assign("<{>","te.KeyProcessBrace();");
}
}
// Unhook needed events/methods for template editing.
DetachTemplateEditing()
{
declare kbd = km.GetKeyboard("Editor");
if (bHooked)
{
bHooked = false;
if (mOriginalTab != NULL)
{
kbd.Assign("<Tab>",mOriginalTab);
mOriginalTab = NULL;
}
if (mOriginalEnter != NULL)
{
kbd.Assign("<Enter>",mOriginalEnter);
mOriginalEnter = NULL;
}
if (mOriginalSpacebar != NULL)
{
kbd.Assign("<Space>",mOriginalSpacebar);
mOriginalSpacebar = NULL;
}
}
}
TimeForExpansion()
{
declare rv = false;
declare ep = editor.TopView.Position;
if (!ep.IsWhiteSpace && ep.Character != 13)
return rv;
declare nColumn = ep.Column;
ep.Save();
ep.MoveCursor(SKIP_RIGHT | SKIP_NONWORD);
if (ep.Column == nColumn || ep.Character == 13)
rv = true;
ep.Restore();
ep.Save();
ep.MoveCursor(SKIP_LEFT | SKIP_WHITE);
ep.Restore();
return rv;
}
CheckForValidExpansion(declare nAdjustment)
{
declare ep = editor.TopView.Position;
// Obtain an edit position.
declare nOriginalColumn = ep.Column;
// Save the position.
ep.Save();
// Move back onto the potential expanding item.
editor.MoveCursorToWordLeft();
// Save our locality.
nRow = ep.Row;
nColumn = ep.Column;
// Get the word.
sExpandableWord = new String("");
if (nOriginalColumn-nColumn > 0)
sExpandableWord = new String(ep.Read(nOriginalColumn-nColumn));
// Restore the position.
ep.Restore();
if (sExpandableWord.Text != "")
{
declare nIndex = 0;
for (nIndex=0;nIndex<nExpansions;nIndex++)
{
declare String sExpansion(aExpansions[nIndex][0]);
if (sExpansion.SubString(0,sExpandableWord.Length).Text == sExpandableWord.Text)
{
nExpandableWord = nIndex;
return true;
}
}
}
return false;
}
ExpansionServices()
{
declare ep = editor.TopView.Position;
// Go back to the begining of the word.
ep.Move(nRow,nColumn);
declare String sCommand(aExpansions[nExpandableWord][1]);
ep.Delete(sExpandableWord.Length);
while (sCommand.Length)
{
switch (sCommand.Integer)
{
case TEC_ALIGNIN:
{
sCommand = sCommand.SubString(2);
ep.Align(1);
break;
}
case TEC_AUTOINDENT:
{
sCommand = sCommand.SubString(2);
ep.InsertCharacter('\r');
break;
}
case TEC_CURSORSET:
{
sCommand = sCommand.SubString(2);
ep.Move(nRow, nColumn);
break;
}
case TEC_CURSORGET:
{
sCommand = sCommand.SubString(2);
nRow = ep.Row;
nColumn = ep.Column;
break;
}
case TEC_INDENT:
{
sCommand = sCommand.SubString(2);
ep.Tab(1);
break;
}
case TEC_INSERT:
{
// Strip off the command.
sCommand = sCommand.SubString(2);
declare nLength = sCommand.Integer;
ep.InsertText(sCommand.SubString(2,nLength).Text);
sCommand = sCommand.SubString(nLength+2);
break;
}
case TEC_OUTDENT:
{
sCommand = sCommand.SubString(2);
ep.Tab(-1);
break;
}
default:
sCommand = sCommand.SubString(2);
}
}
// Put the cusor at the defined location.
if (nRow && nColumn)
ep.Move(nRow,nColumn);
}
KeyProcessBrace()
{
if (bActivated)
{
declare ep = editor.TopView.Position;
ep.InsertText("{");
nRow = ep.Row;
nColumn = ep.Column-1;
if (!nColumn)
nColumn = 1;
sExpandableWord = new String("{");
nExpandableWord = nExpandableBrace;
return ExpansionServices();
}
if (mOriginalBrace == NULL)
editor.TopView.Position.InsertCharacter('{');
else
scriptEngine.Execute(mOriginalBrace);
}
KeyProcessEnter()
{
if (bActivated)
{
declare ep = editor.TopView.Position;
ep.Save();
ep.MoveRelative(0,-1);
if (ep.Character != ';')
{
declare bIndent=true;
ep.MoveCursor(SKIP_LEFT|SKIP_WHITE);
if (ep.Column==1)
bIndent=false;
ep.Restore();
ep.InsertCharacter('\r');
if (bIndent && ep.Column != 1)
ep.Tab(1);
}
else
{
ep.Restore();
ep.InsertCharacter('\r');
}
}
else
{
if (mOriginalEnter == NULL)
editor.TopView.Position.InsertCharacter('\r');
else
scriptEngine.Execute(mOriginalEnter);
}
}
KeyProcessSpace()
{
if (bActivated)
{
if (TimeForExpansion())
{
// Space bar has been pressed.
if (nTemplateActivation > 1)
{
if (AreKeysContinuous())
{
if (nSpaceCount >= nTemplateActivation)
{
nSpaceCount = 0;
// Adjust for multiple spacebar activation.
declare ep = editor.TopView.Position;
ep.MoveRelative(0,-(nTemplateActivation-1));
if (CheckForValidExpansion())
{
// restore position...Delete extra spaces??
ep.MoveRelative(0,nTemplateActivation-1);
ep.BackspaceDelete(nTemplateActivation-1);
return ExpansionServices();
}
}
}
}
else
{
if (CheckForValidExpansion())
return ExpansionServices();
}
}
}
if (mOriginalSpacebar == NULL)
editor.TopView.Position.InsertCharacter(' ');
else
scriptEngine.Execute(mOriginalSpacebar);
}
KeyProcessTab()
{
if (bActivated)
if (TimeForExpansion())
if (CheckForValidExpansion())
return ExpansionServices();
if (mOriginalTab == NULL)
editor.TopView.Position.InsertCharacter('\t');
else
scriptEngine.Execute(mOriginalTab);
}
LoadExpansionFile(declare acFileName)
{
// Remove any old expansions.
nExpansions = 0;
nExpandableBrace = 0;
aExpansions = new array[];
// Load and parse new expansion file.
declare ebExpansions = new EditBuffer(scriptEngine.StartupDirectory + acFileName, true);
if (ebExpansions)
{
declare ep = ebExpansions.Position;
ep.Move(1,1);
declare nIndex;
declare acExpansionCommand;
for (nIndex=0;ep.Row<=ep.LastRow;nIndex++)
{
aExpansions[nIndex] = new array[2];
aExpansions[nIndex][0] = ep.Read();
if (ep.Character == '{')
nExpandableBrace = nIndex;
ep.MoveRelative(1,0);
ep.MoveBOL();
acExpansionCommand = new String(ep.Read());
acExpansionCommand = acExpansionCommand.Trim();
acExpansionCommand = acExpansionCommand.Text + " ";
aExpansions[nIndex][1] = acExpansionCommand;
ep.MoveRelative(1,0);
ep.MoveBOL();
nExpansions++;
}
}
ebExpansions.Destroy();
}
};
// Create instance of Template Editing object.
export declare TemplateEditing te;
_init()
{
te.LoadExpansionFile(te.aExtensions[0][1]);
te.AttachTemplateEditing();
print "Smart and template editing support loaded.";
}
// First thing remove the attachements.
on IDE:>KeyboardAssignmentsChanging(declare acNameOfKbdFile)
{
te.DetachTemplateEditing();
pass(acNameOfKbdFile);
}
// Last thing add the attachements.
on IDE:>KeyboardAssignmentsChanged(declare acNameOfKbdFile)
{
pass(acNameOfKbdFile);
te.AttachTemplateEditing();
}
on editor:>ViewActivated(declare ev)
{
te.DeactivateTemplateEditing();
pass(ev);
declare nIndex = 0;
declare acExtension = new String(ev.Window.Title);
acExtension = acExtension.SubString(acExtension.Index(".",SEARCH_BACKWARD),3);
acExtension = acExtension.Lower();
acExtension = acExtension.Text;
do {
declare String sExtensionList(te.aExtensions[nIndex][0]);
declare acExtensionList = "";
while (sExtensionList != NULL)
{
acExtensionList = sExtensionList.SubString(0,sExtensionList.Index(",")-1).Text;
if (acExtensionList == acExtension)
{
// Attach methods.
if (te.acExpansionFile != te.aExtensions[nIndex][1])
{
te.acExpansionFile = te.aExtensions[nIndex][1];
te.LoadExpansionFile(te.aExtensions[nIndex][1]);
}
te.AtivateTemplateEditing();
return;
}
if (sExtensionList.Index(","))
sExtensionList = sExtensionList.SubString(sExtensionList.Index(","));
else
sExtensionList = NULL;
}
nIndex++;
} while (initialized(te.aExtensions[nIndex]));
}